// baltzo_testloader.t.cpp                                            -*-C++-*-
#include <baltzo_testloader.h>

#include <baltzo_errorcode.h>
#include <baltzo_localtimedescriptor.h>
#include <baltzo_zoneinfo.h>
#include <baltzo_zoneinfobinaryreader.h>

#include <bdlsb_fixedmeminstreambuf.h>
#include <bdlt_date.h>
#include <bdlt_datetime.h>
#include <bdlt_dateutil.h>
#include <bdlt_epochutil.h>
#include <bdlt_time.h>

#include <bslim_testutil.h>
#include <bslma_allocator.h>
#include <bslma_defaultallocatorguard.h>
#include <bslma_testallocator.h>
#include <bslma_usesbslmaallocator.h>
#include <bslmf_assert.h>
#include <bslmf_usesallocator.h>

#include <bsls_assert.h>
#include <bsls_log.h>
#include <bsls_types.h>

#include <bsl_cstdlib.h>
#include <bsl_iostream.h>
#include <bsl_ostream.h>
#include <bsl_sstream.h>

#include <bsls_asserttest.h>

using namespace BloombergLP;
using namespace bsl;

// ============================================================================
//                              TEST PLAN
// ----------------------------------------------------------------------------
//                              Overview
//                              --------
// The component under test provides `baltzo::TestLoader`, a class with a
// simple (easily verified) implementation of the of the `baltzo::Loader`,
// which is used to test components dependent on that protocol.  Once a the
// test loader object is primed (via the overloaded `setTimeZone` method) with
// a set of known `baltzo::Zoneinfo` objects, the `loadTimeZone` method -- the
// sole, non-CREATOR (virtual) method of the protocol -- can be used to obtain
// those objects.  Note that this design is convenient for testing components
// because the user can easily control the timezone information available from
// the loader.
//
// There are two broad concerns in the testing of the `baltzo::TestLoader`
// class:
//  - Does it properly implement the `baltzo::Loader` protocol (i.e., the
//    `loadTimeZone` method)?
//  - Is it a proper (albeit simple) container of `baltzo::Zoneinfo` objects?
// Testing necessarily convolves these areas of concern since `loadTimeZone`
// is, in effect, the only ACCESSOR for the container.  (Formally,
// `loadTimeZone` is not an ACCESSOR because it is non-`const`.)
//
// Although `baltzo::TestLoader` is a container, it is limited functionality,
// so many of the normal container concerns do not apply.
//
// Global Concerns:
//  - No memory is ever allocated from the global allocator.
//  - Any allocated memory is always from the object allocator.
//  - Injected exceptions are safely propagated during memory allocation.
//  - Precondition violations are detected in appropriate build modes.
//
// Global Assumptions:
//  - All explicit memory allocations are presumed to use the global, default,
//    or object allocator.
// ----------------------------------------------------------------------------
// CREATORS
// [ 2] TestLoader();
// [ 2] TestLoader(const allocator_type& allocator);
// [ 2] ~TestLoader();
//
// MANIPULATORS
// [ 3] void setTimeZone(const baltzo::Zoneinfo& tz);
// [ 3] int setTimeZone(const char *tzId, const char *data, int count);
// [ 3] int loadTimeZone(baltzo::Zoneinfo *result, const char *tzId);
//
// ACCESSORS
// [ 2] allocator_type get_allocator() const;
// [ 4] ostream& print(ostream& s, int level = 0, int sPL = 4) const;
//
// FREE OPERATORS
// [ 4] operator<<(ostream& s, const baltzo::TestLoader& tl);
// ----------------------------------------------------------------------------
// [ 1] BREATHING TEST
// [ 5] USAGE EXAMPLE
// [ *] CONCERN: This test driver is reusable w/other, similar components.
// [ *] CONCERN: In no case does memory come from the global allocator.
// [  ] CONCERN: All memory allocation is from the object's allocator.
// [  ] CONCERN: All memory allocation is exception neutral.
// [ 3] CONCERN: Precondition violations are detected when enabled.

// ============================================================================
//                     STANDARD BDE ASSERT TEST FUNCTION
// ----------------------------------------------------------------------------

namespace {

  int testStatus = 0;

  void aSsErT(bool condition, const char *message, int line)
  {
    if (condition) {
      cout << "Error " __FILE__ "(" << line << "): " << message
           << "    (failed)" << endl;

      if (0 <= testStatus && testStatus <= 100) {
        ++testStatus;
      }
    }
  }

}  // close unnamed namespace

// ============================================================================
//               STANDARD BDE TEST DRIVER MACRO ABBREVIATIONS
// ----------------------------------------------------------------------------

#define ASSERT       BSLIM_TESTUTIL_ASSERT
#define ASSERTV      BSLIM_TESTUTIL_ASSERTV

#define LOOP_ASSERT  BSLIM_TESTUTIL_LOOP_ASSERT
#define LOOP0_ASSERT BSLIM_TESTUTIL_LOOP0_ASSERT
#define LOOP1_ASSERT BSLIM_TESTUTIL_LOOP1_ASSERT
#define LOOP2_ASSERT BSLIM_TESTUTIL_LOOP2_ASSERT
#define LOOP3_ASSERT BSLIM_TESTUTIL_LOOP3_ASSERT
#define LOOP4_ASSERT BSLIM_TESTUTIL_LOOP4_ASSERT
#define LOOP5_ASSERT BSLIM_TESTUTIL_LOOP5_ASSERT
#define LOOP6_ASSERT BSLIM_TESTUTIL_LOOP6_ASSERT

#define Q            BSLIM_TESTUTIL_Q   // Quote identifier literally.
#define P            BSLIM_TESTUTIL_P   // Print identifier and value.
#define P_           BSLIM_TESTUTIL_P_  // P(X) without '\n'.
#define T_           BSLIM_TESTUTIL_T_  // Print a tab (w/o newline).
#define L_           BSLIM_TESTUTIL_L_  // current Line number

// ============================================================================
//                     NEGATIVE-TEST MACRO ABBREVIATIONS
// ----------------------------------------------------------------------------
#define ASSERT_FAIL(expr) BSLS_ASSERTTEST_ASSERT_FAIL(expr)
#define ASSERT_PASS(expr) BSLS_ASSERTTEST_ASSERT_PASS(expr)

// ============================================================================
//                   GLOBAL TYPEDEFS/CONSTANTS FOR TESTING
// ----------------------------------------------------------------------------
typedef baltzo::TestLoader Obj;
typedef baltzo::ErrorCode  Err;

// ============================================================================
//                                TYPE TRAITS
// ----------------------------------------------------------------------------

BSLMF_ASSERT(bslma::UsesBslmaAllocator<Obj>::value);
BSLMF_ASSERT((bsl::uses_allocator<Obj, bsl::allocator<char> >::value));

// ============================================================================
//                            TEST TIME ZONE DATA
// ----------------------------------------------------------------------------

static const char *AMERICA_NEW_YORK_ID = "America/New_York";
static const unsigned char  AMERICA_NEW_YORK_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x9e, 0xa6, 0x1e, 0x70,
    0x9f, 0xba, 0xeb, 0x60, 0xa0, 0x86, 0x00, 0x70, 0xa1, 0x9a, 0xcd, 0x60,
    0xa2, 0x65, 0xe2, 0x70, 0xa3, 0x83, 0xe9, 0xe0, 0xa4, 0x6a, 0xae, 0x70,
    0xa5, 0x35, 0xa7, 0x60, 0xa6, 0x53, 0xca, 0xf0, 0xa7, 0x15, 0x89, 0x60,
    0xa8, 0x33, 0xac, 0xf0, 0xa8, 0xfe, 0xa5, 0xe0, 0xaa, 0x13, 0x8e, 0xf0,
    0xaa, 0xde, 0x87, 0xe0, 0xab, 0xf3, 0x70, 0xf0, 0xac, 0xbe, 0x69, 0xe0,
    0xad, 0xd3, 0x52, 0xf0, 0xae, 0x9e, 0x4b, 0xe0, 0xaf, 0xb3, 0x34, 0xf0,
    0xb0, 0x7e, 0x2d, 0xe0, 0xb1, 0x9c, 0x51, 0x70, 0xb2, 0x67, 0x4a, 0x60,
    0xb3, 0x7c, 0x33, 0x70, 0xb4, 0x47, 0x2c, 0x60, 0xb5, 0x5c, 0x15, 0x70,
    0xb6, 0x27, 0x0e, 0x60, 0xb7, 0x3b, 0xf7, 0x70, 0xb8, 0x06, 0xf0, 0x60,
    0xb9, 0x1b, 0xd9, 0x70, 0xb9, 0xe6, 0xd2, 0x60, 0xbb, 0x04, 0xf5, 0xf0,
    0xbb, 0xc6, 0xb4, 0x60, 0xbc, 0xe4, 0xd7, 0xf0, 0xbd, 0xaf, 0xd0, 0xe0,
    0xbe, 0xc4, 0xb9, 0xf0, 0xbf, 0x8f, 0xb2, 0xe0, 0xc0, 0xa4, 0x9b, 0xf0,
    0xc1, 0x6f, 0x94, 0xe0, 0xc2, 0x84, 0x7d, 0xf0, 0xc3, 0x4f, 0x76, 0xe0,
    0xc4, 0x64, 0x5f, 0xf0, 0xc5, 0x2f, 0x58, 0xe0, 0xc6, 0x4d, 0x7c, 0x70,
    0xc7, 0x0f, 0x3a, 0xe0, 0xc8, 0x2d, 0x5e, 0x70, 0xc8, 0xf8, 0x57, 0x60,
    0xca, 0x0d, 0x40, 0x70, 0xca, 0xd8, 0x39, 0x60, 0xcb, 0x88, 0xf0, 0x70,
    0xd2, 0x23, 0xf4, 0x70, 0xd2, 0x60, 0xfb, 0xe0, 0xd3, 0x75, 0xe4, 0xf0,
    0xd4, 0x40, 0xdd, 0xe0, 0xd5, 0x55, 0xc6, 0xf0, 0xd6, 0x20, 0xbf, 0xe0,
    0xd7, 0x35, 0xa8, 0xf0, 0xd8, 0x00, 0xa1, 0xe0, 0xd9, 0x15, 0x8a, 0xf0,
    0xd9, 0xe0, 0x83, 0xe0, 0xda, 0xfe, 0xa7, 0x70, 0xdb, 0xc0, 0x65, 0xe0,
    0xdc, 0xde, 0x89, 0x70, 0xdd, 0xa9, 0x82, 0x60, 0xde, 0xbe, 0x6b, 0x70,
    0xdf, 0x89, 0x64, 0x60, 0xe0, 0x9e, 0x4d, 0x70, 0xe1, 0x69, 0x46, 0x60,
    0xe2, 0x7e, 0x2f, 0x70, 0xe3, 0x49, 0x28, 0x60, 0xe4, 0x5e, 0x11, 0x70,
    0xe5, 0x57, 0x2e, 0xe0, 0xe6, 0x47, 0x2d, 0xf0, 0xe7, 0x37, 0x10, 0xe0,
    0xe8, 0x27, 0x0f, 0xf0, 0xe9, 0x16, 0xf2, 0xe0, 0xea, 0x06, 0xf1, 0xf0,
    0xea, 0xf6, 0xd4, 0xe0, 0xeb, 0xe6, 0xd3, 0xf0, 0xec, 0xd6, 0xb6, 0xe0,
    0xed, 0xc6, 0xb5, 0xf0, 0xee, 0xbf, 0xd3, 0x60, 0xef, 0xaf, 0xd2, 0x70,
    0xf0, 0x9f, 0xb5, 0x60, 0xf1, 0x8f, 0xb4, 0x70, 0xf2, 0x7f, 0x97, 0x60,
    0xf3, 0x6f, 0x96, 0x70, 0xf4, 0x5f, 0x79, 0x60, 0xf5, 0x4f, 0x78, 0x70,
    0xf6, 0x3f, 0x5b, 0x60, 0xf7, 0x2f, 0x5a, 0x70, 0xf8, 0x28, 0x77, 0xe0,
    0xf9, 0x0f, 0x3c, 0x70, 0xfa, 0x08, 0x59, 0xe0, 0xfa, 0xf8, 0x58, 0xf0,
    0xfb, 0xe8, 0x3b, 0xe0, 0xfc, 0xd8, 0x3a, 0xf0, 0xfd, 0xc8, 0x1d, 0xe0,
    0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xa7, 0xff, 0xe0, 0x00, 0x97, 0xfe, 0xf0,
    0x01, 0x87, 0xe1, 0xe0, 0x02, 0x77, 0xe0, 0xf0, 0x03, 0x70, 0xfe, 0x60,
    0x04, 0x60, 0xfd, 0x70, 0x05, 0x50, 0xe0, 0x60, 0x06, 0x40, 0xdf, 0x70,
    0x07, 0x30, 0xc2, 0x60, 0x07, 0x8d, 0x19, 0x70, 0x09, 0x10, 0xa4, 0x60,
    0x09, 0xad, 0x94, 0xf0, 0x0a, 0xf0, 0x86, 0x60, 0x0b, 0xe0, 0x85, 0x70,
    0x0c, 0xd9, 0xa2, 0xe0, 0x0d, 0xc0, 0x67, 0x70, 0x0e, 0xb9, 0x84, 0xe0,
    0x0f, 0xa9, 0x83, 0xf0, 0x10, 0x99, 0x66, 0xe0, 0x11, 0x89, 0x65, 0xf0,
    0x12, 0x79, 0x48, 0xe0, 0x13, 0x69, 0x47, 0xf0, 0x14, 0x59, 0x2a, 0xe0,
    0x15, 0x49, 0x29, 0xf0, 0x16, 0x39, 0x0c, 0xe0, 0x17, 0x29, 0x0b, 0xf0,
    0x18, 0x22, 0x29, 0x60, 0x19, 0x08, 0xed, 0xf0, 0x1a, 0x02, 0x0b, 0x60,
    0x1a, 0xf2, 0x0a, 0x70, 0x1b, 0xe1, 0xed, 0x60, 0x1c, 0xd1, 0xec, 0x70,
    0x1d, 0xc1, 0xcf, 0x60, 0x1e, 0xb1, 0xce, 0x70, 0x1f, 0xa1, 0xb1, 0x60,
    0x20, 0x76, 0x00, 0xf0, 0x21, 0x81, 0x93, 0x60, 0x22, 0x55, 0xe2, 0xf0,
    0x23, 0x6a, 0xaf, 0xe0, 0x24, 0x35, 0xc4, 0xf0, 0x25, 0x4a, 0x91, 0xe0,
    0x26, 0x15, 0xa6, 0xf0, 0x27, 0x2a, 0x73, 0xe0, 0x27, 0xfe, 0xc3, 0x70,
    0x29, 0x0a, 0x55, 0xe0, 0x29, 0xde, 0xa5, 0x70, 0x2a, 0xea, 0x37, 0xe0,
    0x2b, 0xbe, 0x87, 0x70, 0x2c, 0xd3, 0x54, 0x60, 0x2d, 0x9e, 0x69, 0x70,
    0x2e, 0xb3, 0x36, 0x60, 0x2f, 0x7e, 0x4b, 0x70, 0x30, 0x93, 0x18, 0x60,
    0x31, 0x67, 0x67, 0xf0, 0x32, 0x72, 0xfa, 0x60, 0x33, 0x47, 0x49, 0xf0,
    0x34, 0x52, 0xdc, 0x60, 0x35, 0x27, 0x2b, 0xf0, 0x36, 0x32, 0xbe, 0x60,
    0x37, 0x07, 0x0d, 0xf0, 0x38, 0x1b, 0xda, 0xe0, 0x38, 0xe6, 0xef, 0xf0,
    0x39, 0xfb, 0xbc, 0xe0, 0x3a, 0xc6, 0xd1, 0xf0, 0x3b, 0xdb, 0x9e, 0xe0,
    0x3c, 0xaf, 0xee, 0x70, 0x3d, 0xbb, 0x80, 0xe0, 0x3e, 0x8f, 0xd0, 0x70,
    0x3f, 0x9b, 0x62, 0xe0, 0x40, 0x6f, 0xb2, 0x70, 0x41, 0x84, 0x7f, 0x60,
    0x42, 0x4f, 0x94, 0x70, 0x43, 0x64, 0x61, 0x60, 0x44, 0x2f, 0x76, 0x70,
    0x45, 0x44, 0x43, 0x60, 0x45, 0xf3, 0xa8, 0xf0, 0x47, 0x2d, 0x5f, 0xe0,
    0x47, 0xd3, 0x8a, 0xf0, 0x49, 0x0d, 0x41, 0xe0, 0x49, 0xb3, 0x6c, 0xf0,
    0x4a, 0xed, 0x23, 0xe0, 0x4b, 0x9c, 0x89, 0x70, 0x4c, 0xd6, 0x40, 0x60,
    0x4d, 0x7c, 0x6b, 0x70, 0x4e, 0xb6, 0x22, 0x60, 0x4f, 0x5c, 0x4d, 0x70,
    0x50, 0x96, 0x04, 0x60, 0x51, 0x3c, 0x2f, 0x70, 0x52, 0x75, 0xe6, 0x60,
    0x53, 0x1c, 0x11, 0x70, 0x54, 0x55, 0xc8, 0x60, 0x54, 0xfb, 0xf3, 0x70,
    0x56, 0x35, 0xaa, 0x60, 0x56, 0xe5, 0x0f, 0xf0, 0x58, 0x1e, 0xc6, 0xe0,
    0x58, 0xc4, 0xf1, 0xf0, 0x59, 0xfe, 0xa8, 0xe0, 0x5a, 0xa4, 0xd3, 0xf0,
    0x5b, 0xde, 0x8a, 0xe0, 0x5c, 0x84, 0xb5, 0xf0, 0x5d, 0xbe, 0x6c, 0xe0,
    0x5e, 0x64, 0x97, 0xf0, 0x5f, 0x9e, 0x4e, 0xe0, 0x60, 0x4d, 0xb4, 0x70,
    0x61, 0x87, 0x6b, 0x60, 0x62, 0x2d, 0x96, 0x70, 0x63, 0x67, 0x4d, 0x60,
    0x64, 0x0d, 0x78, 0x70, 0x65, 0x47, 0x2f, 0x60, 0x65, 0xed, 0x5a, 0x70,
    0x67, 0x27, 0x11, 0x60, 0x67, 0xcd, 0x3c, 0x70, 0x69, 0x06, 0xf3, 0x60,
    0x69, 0xad, 0x1e, 0x70, 0x6a, 0xe6, 0xd5, 0x60, 0x6b, 0x96, 0x3a, 0xf0,
    0x6c, 0xcf, 0xf1, 0xe0, 0x6d, 0x76, 0x1c, 0xf0, 0x6e, 0xaf, 0xd3, 0xe0,
    0x6f, 0x55, 0xfe, 0xf0, 0x70, 0x8f, 0xb5, 0xe0, 0x71, 0x35, 0xe0, 0xf0,
    0x72, 0x6f, 0x97, 0xe0, 0x73, 0x15, 0xc2, 0xf0, 0x74, 0x4f, 0x79, 0xe0,
    0x74, 0xfe, 0xdf, 0x70, 0x76, 0x38, 0x96, 0x60, 0x76, 0xde, 0xc1, 0x70,
    0x78, 0x18, 0x78, 0x60, 0x78, 0xbe, 0xa3, 0x70, 0x79, 0xf8, 0x5a, 0x60,
    0x7a, 0x9e, 0x85, 0x70, 0x7b, 0xd8, 0x3c, 0x60, 0x7c, 0x7e, 0x67, 0x70,
    0x7d, 0xb8, 0x1e, 0x60, 0x7e, 0x5e, 0x49, 0x70, 0x7f, 0x98, 0x00, 0x60,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x02, 0x03, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0xc7, 0xc0, 0x01,
    0x00, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x04, 0xff, 0xff, 0xc7, 0xc0, 0x01,
    0x08, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x0c, 0x45, 0x44, 0x54, 0x00, 0x45,
    0x53, 0x54, 0x00, 0x45, 0x57, 0x54, 0x00, 0x45, 0x50, 0x54, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x05, 0x00,
    0x00, 0x00, 0x14, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x03, 0xf0, 0x90, 0xff,
    0xff, 0xff, 0xff, 0x9e, 0xa6, 0x1e, 0x70, 0xff, 0xff, 0xff, 0xff, 0x9f,
    0xba, 0xeb, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86, 0x00, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xa1, 0x9a, 0xcd, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa2,
    0x65, 0xe2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x83, 0xe9, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xa4, 0x6a, 0xae, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa5,
    0x35, 0xa7, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa6, 0x53, 0xca, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xa7, 0x15, 0x89, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa8,
    0x33, 0xac, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xa8, 0xfe, 0xa5, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xaa, 0x13, 0x8e, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xaa,
    0xde, 0x87, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xf3, 0x70, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xac, 0xbe, 0x69, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xad,
    0xd3, 0x52, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xae, 0x9e, 0x4b, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xaf, 0xb3, 0x34, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xb0,
    0x7e, 0x2d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x9c, 0x51, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xb2, 0x67, 0x4a, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb3,
    0x7c, 0x33, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x47, 0x2c, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xb5, 0x5c, 0x15, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb6,
    0x27, 0x0e, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x3b, 0xf7, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xb8, 0x06, 0xf0, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb9,
    0x1b, 0xd9, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xe6, 0xd2, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xbb, 0x04, 0xf5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbb,
    0xc6, 0xb4, 0x60, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe4, 0xd7, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xbd, 0xaf, 0xd0, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xbe,
    0xc4, 0xb9, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x8f, 0xb2, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xc0, 0xa4, 0x9b, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc1,
    0x6f, 0x94, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x84, 0x7d, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xc3, 0x4f, 0x76, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc4,
    0x64, 0x5f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc5, 0x2f, 0x58, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xc6, 0x4d, 0x7c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xc7,
    0x0f, 0x3a, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x2d, 0x5e, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xc8, 0xf8, 0x57, 0x60, 0xff, 0xff, 0xff, 0xff, 0xca,
    0x0d, 0x40, 0x70, 0xff, 0xff, 0xff, 0xff, 0xca, 0xd8, 0x39, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xcb, 0x88, 0xf0, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2,
    0x23, 0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x60, 0xfb, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xd3, 0x75, 0xe4, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd4,
    0x40, 0xdd, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x55, 0xc6, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xd6, 0x20, 0xbf, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd7,
    0x35, 0xa8, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x00, 0xa1, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xd9, 0x15, 0x8a, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd9,
    0xe0, 0x83, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xa7, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xdb, 0xc0, 0x65, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xdc,
    0xde, 0x89, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0x82, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xde, 0xbe, 0x6b, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdf,
    0x89, 0x64, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x4d, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xe1, 0x69, 0x46, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe2,
    0x7e, 0x2f, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x28, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xe4, 0x5e, 0x11, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe5,
    0x57, 0x2e, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x2d, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xe7, 0x37, 0x10, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe8,
    0x27, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x16, 0xf2, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xea, 0x06, 0xf1, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xea,
    0xf6, 0xd4, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xd3, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xec, 0xd6, 0xb6, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xed,
    0xc6, 0xb5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xee, 0xbf, 0xd3, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xef, 0xaf, 0xd2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf0,
    0x9f, 0xb5, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xb4, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xf2, 0x7f, 0x97, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf3,
    0x6f, 0x96, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0x79, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xf5, 0x4f, 0x78, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf6,
    0x3f, 0x5b, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x5a, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xf8, 0x28, 0x77, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xf9,
    0x0f, 0x3c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x59, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xfa, 0xf8, 0x58, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xfb,
    0xe8, 0x3b, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x3a, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xfd, 0xc8, 0x1d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfe,
    0xb8, 0x1c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0xff, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x97, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x87, 0xe1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x77, 0xe0, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x03, 0x70, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x60, 0xfd, 0x70, 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0xe0, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x06, 0x40, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x07,
    0x30, 0xc2, 0x60, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x19, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x09, 0x10, 0xa4, 0x60, 0x00, 0x00, 0x00, 0x00, 0x09,
    0xad, 0x94, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x86, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x0b, 0xe0, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0c,
    0xd9, 0xa2, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x67, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x0e, 0xb9, 0x84, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f,
    0xa9, 0x83, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x66, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x11, 0x89, 0x65, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x12,
    0x79, 0x48, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x47, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x14, 0x59, 0x2a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x15,
    0x49, 0x29, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x0c, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x17, 0x29, 0x0b, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x18,
    0x22, 0x29, 0x60, 0x00, 0x00, 0x00, 0x00, 0x19, 0x08, 0xed, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x1a, 0x02, 0x0b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1a,
    0xf2, 0x0a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0xed, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x1c, 0xd1, 0xec, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1d,
    0xc1, 0xcf, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xce, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x1f, 0xa1, 0xb1, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20,
    0x76, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0x93, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x22, 0x55, 0xe2, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x23,
    0x6a, 0xaf, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xc4, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x25, 0x4a, 0x91, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x26,
    0x15, 0xa6, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x73, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x27, 0xfe, 0xc3, 0x70, 0x00, 0x00, 0x00, 0x00, 0x29,
    0x0a, 0x55, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xa5, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x2a, 0xea, 0x37, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x2b,
    0xbe, 0x87, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x54, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x2d, 0x9e, 0x69, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2e,
    0xb3, 0x36, 0x60, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x4b, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x30, 0x93, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x31,
    0x67, 0x67, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xfa, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x33, 0x47, 0x49, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x34,
    0x52, 0xdc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x2b, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x36, 0x32, 0xbe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x37,
    0x07, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0xda, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x38, 0xe6, 0xef, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x39,
    0xfb, 0xbc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xd1, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x3b, 0xdb, 0x9e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3c,
    0xaf, 0xee, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x80, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x3e, 0x8f, 0xd0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3f,
    0x9b, 0x62, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb2, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x41, 0x84, 0x7f, 0x60, 0x00, 0x00, 0x00, 0x00, 0x42,
    0x4f, 0x94, 0x70, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x61, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x44, 0x2f, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, 0x45,
    0x44, 0x43, 0x60, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xa8, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x47, 0x2d, 0x5f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x47,
    0xd3, 0x8a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x41, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x49, 0xb3, 0x6c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x4a,
    0xed, 0x23, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0x89, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x4c, 0xd6, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x4d,
    0x7c, 0x6b, 0x70, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x22, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x4f, 0x5c, 0x4d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x50,
    0x96, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x2f, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x52, 0x75, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x53,
    0x1c, 0x11, 0x70, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xc8, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x54, 0xfb, 0xf3, 0x70, 0x00, 0x00, 0x00, 0x00, 0x56,
    0x35, 0xaa, 0x60, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x0f, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x58, 0x1e, 0xc6, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x58,
    0xc4, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xa8, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x5a, 0xa4, 0xd3, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5b,
    0xde, 0x8a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xb5, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x5d, 0xbe, 0x6c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5e,
    0x64, 0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x4e, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x60, 0x4d, 0xb4, 0x70, 0x00, 0x00, 0x00, 0x00, 0x61,
    0x87, 0x6b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0x96, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x63, 0x67, 0x4d, 0x60, 0x00, 0x00, 0x00, 0x00, 0x64,
    0x0d, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x2f, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x65, 0xed, 0x5a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x67,
    0x27, 0x11, 0x60, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x3c, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x69, 0x06, 0xf3, 0x60, 0x00, 0x00, 0x00, 0x00, 0x69,
    0xad, 0x1e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xd5, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x6b, 0x96, 0x3a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x6c,
    0xcf, 0xf1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x1c, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x6e, 0xaf, 0xd3, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6f,
    0x55, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xb5, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x71, 0x35, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x72,
    0x6f, 0x97, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xc2, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x74, 0x4f, 0x79, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x74,
    0xfe, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0x96, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x76, 0xde, 0xc1, 0x70, 0x00, 0x00, 0x00, 0x00, 0x78,
    0x18, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xa3, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x79, 0xf8, 0x5a, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7a,
    0x9e, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x3c, 0x60, 0x00,
    0x00, 0x00, 0x00, 0x7c, 0x7e, 0x67, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7d,
    0xb8, 0x1e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x49, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x7f, 0x98, 0x00, 0x60, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01,
    0x02, 0x01, 0x02, 0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff, 0xff, 0xc7,
    0xc0, 0x01, 0x04, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff, 0xff, 0xc7,
    0xc0, 0x01, 0x0c, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c, 0x4d, 0x54,
    0x00, 0x45, 0x44, 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, 0x57, 0x54,
    0x00, 0x45, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44, 0x54, 0x2c,
    0x4d, 0x33, 0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31, 0x2e, 0x31,
    0x2e, 0x30, 0x0a
};

static const char *EUROPE_ROME_ID = "Europe/Rome";
static const unsigned char  EUROPE_ROME_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
    0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa,
    0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x9b, 0x37, 0xa6, 0xf0,
    0x9b, 0xd5, 0xda, 0xf0, 0x9c, 0xc5, 0xcb, 0xf0, 0x9d, 0xb5, 0xbc, 0xf0,
    0x9e, 0x89, 0xfe, 0x70, 0x9f, 0x9e, 0xd9, 0x70, 0xa0, 0x60, 0xa5, 0xf0,
    0xa1, 0x7e, 0xbb, 0x70, 0xa2, 0x5c, 0x37, 0x70, 0xa3, 0x4c, 0x28, 0x70,
    0xc8, 0x6c, 0x35, 0xf0, 0xcc, 0xe7, 0x4b, 0x10, 0xcd, 0xa9, 0x17, 0x90,
    0xce, 0xa2, 0x43, 0x10, 0xcf, 0x92, 0x34, 0x10, 0xd0, 0x07, 0x5f, 0x60,
    0xd0, 0x6e, 0x42, 0x70, 0xd1, 0x72, 0x16, 0x10, 0xd2, 0x4c, 0xd2, 0xf0,
    0xd3, 0x3e, 0x31, 0x90, 0xd4, 0x49, 0xd2, 0x10, 0xd5, 0x1d, 0xf7, 0x70,
    0xd6, 0x29, 0x97, 0xf0, 0xd6, 0xeb, 0x80, 0x90, 0xd8, 0x09, 0x96, 0x10,
    0xf9, 0x33, 0xb5, 0xf0, 0xf9, 0xd9, 0xc4, 0xe0, 0xfb, 0x1c, 0xd2, 0x70,
    0xfb, 0xb9, 0xa6, 0xe0, 0xfc, 0xfc, 0xb4, 0x70, 0xfd, 0x99, 0x88, 0xe0,
    0xfe, 0xe5, 0xd0, 0xf0, 0xff, 0x82, 0xa5, 0x60, 0x00, 0xc5, 0xb2, 0xf0,
    0x01, 0x62, 0x87, 0x60, 0x02, 0x9c, 0x5a, 0x70, 0x03, 0x42, 0x77, 0x70,
    0x04, 0x85, 0x76, 0xf0, 0x05, 0x2b, 0x85, 0xe0, 0x06, 0x6e, 0x93, 0x70,
    0x07, 0x0b, 0x67, 0xe0, 0x08, 0x45, 0x3a, 0xf0, 0x08, 0xeb, 0x49, 0xe0,
    0x0a, 0x2e, 0x57, 0x70, 0x0a, 0xcb, 0x39, 0xf0, 0x0c, 0x0e, 0x39, 0x70,
    0x0c, 0xab, 0x1b, 0xf0, 0x0d, 0xe4, 0xe0, 0xf0, 0x0e, 0x8a, 0xfd, 0xf0,
    0x0f, 0xcd, 0xfd, 0x70, 0x10, 0x74, 0x1a, 0x70, 0x11, 0xad, 0xdf, 0x70,
    0x12, 0x53, 0xfc, 0x70, 0x12, 0xce, 0x97, 0xf0, 0x13, 0x4d, 0x44, 0x10,
    0x14, 0x33, 0xfa, 0x90, 0x15, 0x23, 0xeb, 0x90, 0x16, 0x13, 0xdc, 0x90,
    0x17, 0x03, 0xcd, 0x90, 0x17, 0xf3, 0xbe, 0x90, 0x18, 0xe3, 0xaf, 0x90,
    0x19, 0xd3, 0xa0, 0x90, 0x1a, 0xc3, 0x91, 0x90, 0x1b, 0xbc, 0xbd, 0x10,
    0x1c, 0xac, 0xae, 0x10, 0x1d, 0x9c, 0x9f, 0x10, 0x1e, 0x8c, 0x90, 0x10,
    0x1f, 0x7c, 0x81, 0x10, 0x20, 0x6c, 0x72, 0x10, 0x21, 0x5c, 0x63, 0x10,
    0x22, 0x4c, 0x54, 0x10, 0x23, 0x3c, 0x45, 0x10, 0x24, 0x2c, 0x36, 0x10,
    0x25, 0x1c, 0x27, 0x10, 0x26, 0x0c, 0x18, 0x10, 0x27, 0x05, 0x43, 0x90,
    0x27, 0xf5, 0x34, 0x90, 0x28, 0xe5, 0x25, 0x90, 0x29, 0xd5, 0x16, 0x90,
    0x2a, 0xc5, 0x07, 0x90, 0x2b, 0xb4, 0xf8, 0x90, 0x2c, 0xa4, 0xe9, 0x90,
    0x2d, 0x94, 0xda, 0x90, 0x2e, 0x84, 0xcb, 0x90, 0x2f, 0x74, 0xbc, 0x90,
    0x30, 0x64, 0xad, 0x90, 0x31, 0x5d, 0xd9, 0x10, 0x32, 0x72, 0xb4, 0x10,
    0x33, 0x3d, 0xbb, 0x10, 0x34, 0x52, 0x96, 0x10, 0x35, 0x1d, 0x9d, 0x10,
    0x36, 0x32, 0x78, 0x10, 0x36, 0xfd, 0x7f, 0x10, 0x38, 0x1b, 0x94, 0x90,
    0x38, 0xdd, 0x61, 0x10, 0x39, 0xfb, 0x76, 0x90, 0x3a, 0xbd, 0x43, 0x10,
    0x3b, 0xdb, 0x58, 0x90, 0x3c, 0xa6, 0x5f, 0x90, 0x3d, 0xbb, 0x3a, 0x90,
    0x3e, 0x86, 0x41, 0x90, 0x3f, 0x9b, 0x1c, 0x90, 0x40, 0x66, 0x23, 0x90,
    0x41, 0x84, 0x39, 0x10, 0x42, 0x46, 0x05, 0x90, 0x43, 0x64, 0x1b, 0x10,
    0x44, 0x25, 0xe7, 0x90, 0x45, 0x43, 0xfd, 0x10, 0x46, 0x05, 0xc9, 0x90,
    0x47, 0x23, 0xdf, 0x10, 0x47, 0xee, 0xe6, 0x10, 0x49, 0x03, 0xc1, 0x10,
    0x49, 0xce, 0xc8, 0x10, 0x4a, 0xe3, 0xa3, 0x10, 0x4b, 0xae, 0xaa, 0x10,
    0x4c, 0xcc, 0xbf, 0x90, 0x4d, 0x8e, 0x8c, 0x10, 0x4e, 0xac, 0xa1, 0x90,
    0x4f, 0x6e, 0x6e, 0x10, 0x50, 0x8c, 0x83, 0x90, 0x51, 0x57, 0x8a, 0x90,
    0x52, 0x6c, 0x65, 0x90, 0x53, 0x37, 0x6c, 0x90, 0x54, 0x4c, 0x47, 0x90,
    0x55, 0x17, 0x4e, 0x90, 0x56, 0x2c, 0x29, 0x90, 0x56, 0xf7, 0x30, 0x90,
    0x58, 0x15, 0x46, 0x10, 0x58, 0xd7, 0x12, 0x90, 0x59, 0xf5, 0x28, 0x10,
    0x5a, 0xb6, 0xf4, 0x90, 0x5b, 0xd5, 0x0a, 0x10, 0x5c, 0xa0, 0x11, 0x10,
    0x5d, 0xb4, 0xec, 0x10, 0x5e, 0x7f, 0xf3, 0x10, 0x5f, 0x94, 0xce, 0x10,
    0x60, 0x5f, 0xd5, 0x10, 0x61, 0x7d, 0xea, 0x90, 0x62, 0x3f, 0xb7, 0x10,
    0x63, 0x5d, 0xcc, 0x90, 0x64, 0x1f, 0x99, 0x10, 0x65, 0x3d, 0xae, 0x90,
    0x66, 0x08, 0xb5, 0x90, 0x67, 0x1d, 0x90, 0x90, 0x67, 0xe8, 0x97, 0x90,
    0x68, 0xfd, 0x72, 0x90, 0x69, 0xc8, 0x79, 0x90, 0x6a, 0xdd, 0x54, 0x90,
    0x6b, 0xa8, 0x5b, 0x90, 0x6c, 0xc6, 0x71, 0x10, 0x6d, 0x88, 0x3d, 0x90,
    0x6e, 0xa6, 0x53, 0x10, 0x6f, 0x68, 0x1f, 0x90, 0x70, 0x86, 0x35, 0x10,
    0x71, 0x51, 0x3c, 0x10, 0x72, 0x66, 0x17, 0x10, 0x73, 0x31, 0x1e, 0x10,
    0x74, 0x45, 0xf9, 0x10, 0x75, 0x11, 0x00, 0x10, 0x76, 0x2f, 0x15, 0x90,
    0x76, 0xf0, 0xe2, 0x10, 0x78, 0x0e, 0xf7, 0x90, 0x78, 0xd0, 0xc4, 0x10,
    0x79, 0xee, 0xd9, 0x90, 0x7a, 0xb0, 0xa6, 0x10, 0x7b, 0xce, 0xbb, 0x90,
    0x7c, 0x99, 0xc2, 0x90, 0x7d, 0xae, 0x9d, 0x90, 0x7e, 0x79, 0xa4, 0x90,
    0x7f, 0x8e, 0x7f, 0x90, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x01, 0x02, 0x01, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02,
    0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x00,
    0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x00,
    0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x00, 0x00, 0x1c, 0x20, 0x01, 0x00,
    0x00, 0x00, 0x0e, 0x10, 0x00, 0x05, 0x43, 0x45, 0x53, 0x54, 0x00, 0x43,
    0x45, 0x54, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
    0x00, 0x01, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0xff,
    0xff, 0xff, 0xff, 0x3d, 0xbe, 0x1e, 0xcc, 0xff, 0xff, 0xff, 0xff, 0x70,
    0xbc, 0x83, 0xcc, 0xff, 0xff, 0xff, 0xff, 0x9b, 0x37, 0xa6, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0x9b, 0xd5, 0xda, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x9c,
    0xc5, 0xcb, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x9d, 0xb5, 0xbc, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0x9e, 0x89, 0xfe, 0x70, 0xff, 0xff, 0xff, 0xff, 0x9f,
    0x9e, 0xd9, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x60, 0xa5, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xa1, 0x7e, 0xbb, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa2,
    0x5c, 0x37, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x4c, 0x28, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xc8, 0x6c, 0x35, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xcc,
    0xe7, 0x4b, 0x10, 0xff, 0xff, 0xff, 0xff, 0xcd, 0xa9, 0x17, 0x90, 0xff,
    0xff, 0xff, 0xff, 0xce, 0xa2, 0x43, 0x10, 0xff, 0xff, 0xff, 0xff, 0xcf,
    0x92, 0x34, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x07, 0x5f, 0x60, 0xff,
    0xff, 0xff, 0xff, 0xd0, 0x6e, 0x42, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd1,
    0x72, 0x16, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x4c, 0xd2, 0xf0, 0xff,
    0xff, 0xff, 0xff, 0xd3, 0x3e, 0x31, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd4,
    0x49, 0xd2, 0x10, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x1d, 0xf7, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xd6, 0x29, 0x97, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd6,
    0xeb, 0x80, 0x90, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x09, 0x96, 0x10, 0xff,
    0xff, 0xff, 0xff, 0xf9, 0x33, 0xb5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xf9,
    0xd9, 0xc4, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x1c, 0xd2, 0x70, 0xff,
    0xff, 0xff, 0xff, 0xfb, 0xb9, 0xa6, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc,
    0xfc, 0xb4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x99, 0x88, 0xe0, 0xff,
    0xff, 0xff, 0xff, 0xfe, 0xe5, 0xd0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
    0x82, 0xa5, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xb2, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x62, 0x87, 0x60, 0x00, 0x00, 0x00, 0x00, 0x02,
    0x9c, 0x5a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x03, 0x42, 0x77, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x04, 0x85, 0x76, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x05,
    0x2b, 0x85, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x06, 0x6e, 0x93, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x07, 0x0b, 0x67, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x08,
    0x45, 0x3a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x08, 0xeb, 0x49, 0xe0, 0x00,
    0x00, 0x00, 0x00, 0x0a, 0x2e, 0x57, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0a,
    0xcb, 0x39, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0e, 0x39, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x0c, 0xab, 0x1b, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0d,
    0xe4, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x8a, 0xfd, 0xf0, 0x00,
    0x00, 0x00, 0x00, 0x0f, 0xcd, 0xfd, 0x70, 0x00, 0x00, 0x00, 0x00, 0x10,
    0x74, 0x1a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x11, 0xad, 0xdf, 0x70, 0x00,
    0x00, 0x00, 0x00, 0x12, 0x53, 0xfc, 0x70, 0x00, 0x00, 0x00, 0x00, 0x12,
    0xce, 0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4d, 0x44, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x14, 0x33, 0xfa, 0x90, 0x00, 0x00, 0x00, 0x00, 0x15,
    0x23, 0xeb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x16, 0x13, 0xdc, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x17, 0x03, 0xcd, 0x90, 0x00, 0x00, 0x00, 0x00, 0x17,
    0xf3, 0xbe, 0x90, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0xaf, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x19, 0xd3, 0xa0, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1a,
    0xc3, 0x91, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xbc, 0xbd, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x1c, 0xac, 0xae, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1d,
    0x9c, 0x9f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x8c, 0x90, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x1f, 0x7c, 0x81, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20,
    0x6c, 0x72, 0x10, 0x00, 0x00, 0x00, 0x00, 0x21, 0x5c, 0x63, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x22, 0x4c, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x23,
    0x3c, 0x45, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2c, 0x36, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x25, 0x1c, 0x27, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26,
    0x0c, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x27, 0x05, 0x43, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x27, 0xf5, 0x34, 0x90, 0x00, 0x00, 0x00, 0x00, 0x28,
    0xe5, 0x25, 0x90, 0x00, 0x00, 0x00, 0x00, 0x29, 0xd5, 0x16, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x2a, 0xc5, 0x07, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2b,
    0xb4, 0xf8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xa4, 0xe9, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x2d, 0x94, 0xda, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2e,
    0x84, 0xcb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x74, 0xbc, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x30, 0x64, 0xad, 0x90, 0x00, 0x00, 0x00, 0x00, 0x31,
    0x5d, 0xd9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xb4, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x33, 0x3d, 0xbb, 0x10, 0x00, 0x00, 0x00, 0x00, 0x34,
    0x52, 0x96, 0x10, 0x00, 0x00, 0x00, 0x00, 0x35, 0x1d, 0x9d, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x36, 0x32, 0x78, 0x10, 0x00, 0x00, 0x00, 0x00, 0x36,
    0xfd, 0x7f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0x94, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x38, 0xdd, 0x61, 0x10, 0x00, 0x00, 0x00, 0x00, 0x39,
    0xfb, 0x76, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xbd, 0x43, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x3b, 0xdb, 0x58, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3c,
    0xa6, 0x5f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x3a, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x3e, 0x86, 0x41, 0x90, 0x00, 0x00, 0x00, 0x00, 0x3f,
    0x9b, 0x1c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x40, 0x66, 0x23, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x41, 0x84, 0x39, 0x10, 0x00, 0x00, 0x00, 0x00, 0x42,
    0x46, 0x05, 0x90, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x1b, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x44, 0x25, 0xe7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x45,
    0x43, 0xfd, 0x10, 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0xc9, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x47, 0x23, 0xdf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x47,
    0xee, 0xe6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x49, 0x03, 0xc1, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x49, 0xce, 0xc8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4a,
    0xe3, 0xa3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xae, 0xaa, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x4c, 0xcc, 0xbf, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4d,
    0x8e, 0x8c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xac, 0xa1, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x4f, 0x6e, 0x6e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x50,
    0x8c, 0x83, 0x90, 0x00, 0x00, 0x00, 0x00, 0x51, 0x57, 0x8a, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x52, 0x6c, 0x65, 0x90, 0x00, 0x00, 0x00, 0x00, 0x53,
    0x37, 0x6c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x54, 0x4c, 0x47, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x55, 0x17, 0x4e, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56,
    0x2c, 0x29, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56, 0xf7, 0x30, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x58, 0x15, 0x46, 0x10, 0x00, 0x00, 0x00, 0x00, 0x58,
    0xd7, 0x12, 0x90, 0x00, 0x00, 0x00, 0x00, 0x59, 0xf5, 0x28, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x5a, 0xb6, 0xf4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x5b,
    0xd5, 0x0a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5c, 0xa0, 0x11, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x5d, 0xb4, 0xec, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5e,
    0x7f, 0xf3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x94, 0xce, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x60, 0x5f, 0xd5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x61,
    0x7d, 0xea, 0x90, 0x00, 0x00, 0x00, 0x00, 0x62, 0x3f, 0xb7, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x63, 0x5d, 0xcc, 0x90, 0x00, 0x00, 0x00, 0x00, 0x64,
    0x1f, 0x99, 0x10, 0x00, 0x00, 0x00, 0x00, 0x65, 0x3d, 0xae, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x66, 0x08, 0xb5, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67,
    0x1d, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0xe8, 0x97, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x68, 0xfd, 0x72, 0x90, 0x00, 0x00, 0x00, 0x00, 0x69,
    0xc8, 0x79, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xdd, 0x54, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x6b, 0xa8, 0x5b, 0x90, 0x00, 0x00, 0x00, 0x00, 0x6c,
    0xc6, 0x71, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x88, 0x3d, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x6e, 0xa6, 0x53, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6f,
    0x68, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x70, 0x86, 0x35, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x71, 0x51, 0x3c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x72,
    0x66, 0x17, 0x10, 0x00, 0x00, 0x00, 0x00, 0x73, 0x31, 0x1e, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x74, 0x45, 0xf9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x75,
    0x11, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x76, 0x2f, 0x15, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x76, 0xf0, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x00, 0x78,
    0x0e, 0xf7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd0, 0xc4, 0x10, 0x00,
    0x00, 0x00, 0x00, 0x79, 0xee, 0xd9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7a,
    0xb0, 0xa6, 0x10, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xce, 0xbb, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x7c, 0x99, 0xc2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7d,
    0xae, 0x9d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x79, 0xa4, 0x90, 0x00,
    0x00, 0x00, 0x00, 0x7f, 0x8e, 0x7f, 0x90, 0x01, 0x03, 0x02, 0x03, 0x02,
    0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02,
    0x04, 0x03, 0x04, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05,
    0x04, 0x05, 0x04, 0x05, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03,
    0x02, 0x03, 0x05, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
    0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x00,
    0x00, 0x0b, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xb4, 0x00, 0x04, 0x00,
    0x00, 0x1c, 0x20, 0x01, 0x08, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x0d, 0x00,
    0x00, 0x1c, 0x20, 0x01, 0x08, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x0d, 0x00,
    0x00, 0x1c, 0x20, 0x01, 0x08, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x0d, 0x4c,
    0x4d, 0x54, 0x00, 0x52, 0x4d, 0x54, 0x00, 0x43, 0x45, 0x53, 0x54, 0x00,
    0x43, 0x45, 0x54, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0a, 0x43, 0x45, 0x54,
    0x2d, 0x31, 0x43, 0x45, 0x53, 0x54, 0x2c, 0x4d, 0x33, 0x2e, 0x35, 0x2e,
    0x30, 0x2c, 0x4d, 0x31, 0x30, 0x2e, 0x35, 0x2e, 0x30, 0x2f, 0x33, 0x0a,
};

// Asia/Saigon
static const char *ASIA_SAIGON_ID = "Asia/Saigon";
static const unsigned char  ASIA_SAIGON_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x88, 0x6f, 0x42, 0x80,
    0x91, 0x5f, 0xee, 0xd0, 0x93, 0x85, 0xb1, 0x90, 0xb7, 0x41, 0xbc, 0x00,
    0x01, 0x02, 0x03, 0x02, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x63, 0xec, 0x00, 0x04, 0x00, 0x00, 0x62, 0x70, 0x00, 0x08, 0x00, 0x00,
    0x70, 0x80, 0x00, 0x08, 0x4c, 0x4d, 0x54, 0x00, 0x53, 0x4d, 0x54, 0x00,
    0x49, 0x43, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0xff, 0xff, 0xff, 0xff,
    0x88, 0x6f, 0x42, 0x80, 0xff, 0xff, 0xff, 0xff, 0x91, 0x5f, 0xee, 0xd0,
    0xff, 0xff, 0xff, 0xff, 0x93, 0x85, 0xb1, 0x90, 0xff, 0xff, 0xff, 0xff,
    0xb7, 0x41, 0xbc, 0x00, 0x01, 0x02, 0x03, 0x02, 0x00, 0x00, 0x64, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x63, 0xec, 0x00, 0x04, 0x00, 0x00, 0x62, 0x70,
    0x00, 0x08, 0x00, 0x00, 0x70, 0x80, 0x00, 0x08, 0x4c, 0x4d, 0x54, 0x00,
    0x53, 0x4d, 0x54, 0x00, 0x49, 0x43, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x43, 0x54, 0x2d, 0x37, 0x0a,
};

static const char *ASIA_BANGKOK_ID = "Asia/Bangkok";
static const unsigned char  ASIA_BANGKOK_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0xa2, 0x6a, 0x67, 0xc4,
    0x01, 0x00, 0x00, 0x5e, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x62, 0x70, 0x00,
    0x04, 0x42, 0x4d, 0x54, 0x00, 0x49, 0x43, 0x54, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0xff, 0xff, 0xff,
    0xff, 0x56, 0xb6, 0x85, 0xc4, 0xff, 0xff, 0xff, 0xff, 0xa2, 0x6a, 0x67,
    0xc4, 0x01, 0x02, 0x00, 0x00, 0x5e, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x5e,
    0x3c, 0x00, 0x04, 0x00, 0x00, 0x62, 0x70, 0x00, 0x08, 0x4c, 0x4d, 0x54,
    0x00, 0x42, 0x4d, 0x54, 0x00, 0x49, 0x43, 0x54, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x0a, 0x49, 0x43, 0x54, 0x2d, 0x37, 0x0a
};

// ============================================================================
//                        GLOBAL CLASSES FOR TESTING
// ----------------------------------------------------------------------------

/// The Logger verbosity guard disables logging on construction, and
/// re-enables logging, based on the prior default pass-through level, when
/// it goes out of scope and is destroyed.  It is intended to suppress
/// logged output for intentional errors when the test driver is run in
/// non-verbose mode.
struct LogVerbosityGuard {

    bool                    d_verbose;             // verbose mode does not
                                                   // disable logging

    bsls::LogSeverity::Enum d_defaultPassthrough;  // default passthrough
                                                   // log level

    /// If the optionally specified `verbose` is `false` disable logging
    /// until this guard is destroyed.
    explicit LogVerbosityGuard(bool verbose = false)
    {
        d_verbose            = verbose;
        d_defaultPassthrough = bsls::Log::severityThreshold();

        if (!d_verbose) {
            bsls::Log::setSeverityThreshold(bsls::LogSeverity::e_FATAL);
        }
    }

    /// Set the logging verbosity back to its default state.
    ~LogVerbosityGuard()
    {
        if (!d_verbose) {
            bsls::Log::setSeverityThreshold(d_defaultPassthrough);
        }
    }
};

// ============================================================================
//                       GLOBAL FUNCTIONS FOR TESTING
// ----------------------------------------------------------------------------

/// Return the result of invoking the `print` method of the specified
/// `zoneinfo` object at the specified `level` plus 1 at the specified
/// `spacesPerLevel` and indentation of the first line suppressed.
/// Optionally specify a `basicAllocator` used to supply memory.  If
/// `basicAllocator` is 0, the currently installed default allocator is
/// used.
bsl::string fmtZoneinfoIdent1(const baltzo::Zoneinfo&  zoneinfo,
                              int                      level,
                              int                      spacesPerLevel,
                              bslma::Allocator        *basicAllocator = 0)
{
    level = level < 0 ? -level : level;
    ++level;

    ostringstream os(basicAllocator);
    zoneinfo.print(os, -level, spacesPerLevel);
    return os.str();
}

// ============================================================================
//                               MAIN PROGRAM
// ----------------------------------------------------------------------------

int main(int argc, char *argv[])
{
    int                 test = argc > 1 ? atoi(argv[1]) : 0;
    bool             verbose = argc > 2;
    bool         veryVerbose = argc > 3;
    bool     veryVeryVerbose = argc > 4;
    bool veryVeryVeryVerbose = argc > 5;

    cout << "TEST " << __FILE__ << " CASE " << test << endl;

    // CONCERN: This test driver is reusable w/other, similar components.

    // CONCERN: In no case does memory come from the global allocator.

    bslma::TestAllocator          globalAllocator("gA", veryVeryVeryVerbose);
    bslma::Default::setGlobalAllocator(&globalAllocator);

    bslma::TestAllocator          allocator("zA", veryVeryVeryVerbose);
    bslma::TestAllocator         *Z = &allocator;
    bslma::TestAllocator          defaultAllocator("dA", veryVeryVeryVerbose);
    bslma::DefaultAllocatorGuard  guard(&defaultAllocator);

    switch (test) { case 0:
      case 5: {
        // --------------------------------------------------------------------
        // TESTING USAGE EXAMPLE
        //
        // Concerns:
        //   The usage example provided in the component header file must
        //   compile, link, and run on all platforms as shown.
        //
        // Plan:
        //   Incorporate usage example from header into driver, remove leading
        //   comment characters, and replace `assert` with `ASSERT`.
        //
        // Testing:
        //   USAGE EXAMPLE
        // --------------------------------------------------------------------

        if (verbose) cout << "\nTesting Usage Example"
                          << "\n=====================" << endl;
///Usage
///-----
// The following examples demonstrate how to populate a `baltzo::TestLoader`
// with time-zone information, and then access that information through the
// `baltzo::Loader` protocol.
//
///Example 1: Populating a `baltzo::TestLoader` with Time-Zone Information
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// We start by creating a `baltzo::Zoneinfo` object, which we will eventually
// populate with a subset of data for "America/New_York":
// ```
    baltzo::Zoneinfo newYorkTimeZone;
// ```
// Next, we populate `newYorkTimeZone` with the correct time-zone identifier
// and two types of local time (standard time, and daylight-saving time):
// ```
    const char *NEW_YORK_ID = "America/New_York";
    newYorkTimeZone.setIdentifier(NEW_YORK_ID);

    baltzo::LocalTimeDescriptor est(-5 * 60 * 60, false, "EST");
    baltzo::LocalTimeDescriptor edt(-4 * 60 * 60, true,  "EDT");
// ```
// Then, we create a series of transitions between these local time
// descriptors for the years 2007-2011.  Note that the United States
// transitions to daylight saving time on the second Sunday in March, at 2am
// local time (7am GMT), and transitions back to standard time on the first
// Sunday in November at 2am local time (6am GMT).  Also note, that these rules
// for generating transitions was different prior to 2007, and may be changed
// at some point in the future.
// ```
    bdlt::Time edtTime(7, 0, 0);  // UTC transition time
    bdlt::Time estTime(6, 0, 0);  // UTC transition time
    static const int edtDays[5] = { 11,  9,  8, 14, 13 };
    static const int estDays[5] = {  4,  2,  1,  7,  6 };
    for (int year = 2007; year < 2012; ++year) {
        int edtDay = edtDays[year - 2007];
        int estDay = estDays[year - 2007];

        bdlt::Datetime edtTransition(bdlt::Date(year, 3,  edtDay), edtTime);
        bdlt::Datetime estTransition(bdlt::Date(year, 11, estDay), estTime);

        bsls::Types::Int64 edtTransitionT =
                       bdlt::EpochUtil::convertToTimeT64(edtTransition);

        bsls::Types::Int64 estTransitionT =
                       bdlt::EpochUtil::convertToTimeT64(estTransition);
// ```
// Now, having created values representing the daylight saving time
// transitions (in UTC), we insert the transitions into the `baltzo::Zoneinfo`
// object `newYorkTimeZone`:
// ```
        newYorkTimeZone.addTransition(edtTransitionT, edt);
        newYorkTimeZone.addTransition(estTransitionT, est);
    }
// ```
// Now, we create a `baltzo::TestLoader` object and configure it with
// `newYorkTimeZone`, which the test loader will associate with the identifier
// `newYorkTimeZone.identifier()` (whose value is "America/New_York"):
// ```
    baltzo::TestLoader testLoader;
    testLoader.setTimeZone(newYorkTimeZone);
// ```
//
///Example 2: Accessing Time-Zone Information From a `baltzo::TestLoader`
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// In the next example, we will use the `baltzo::TestLoader` we initialized in
// the preceding example, to load time-zone information for New York via the
// `baltzo::Loader` protocol.
//
// We start by creating a `baltzo::Loader` reference to `testLoader`:
// ```
    baltzo::Loader& loader = testLoader;
// ```
// Now we used the protocol method `loadTimeZone` to load time-zone
// information for New York:
// ```
    baltzo::Zoneinfo resultNewYork;
    int status = loader.loadTimeZone(&resultNewYork, "America/New_York");
    ASSERT(0 == status);
// ```
// Finally, we verify that the returned time-zone information,
// `resultNewYork`, is equivalent to `newYorkTimeZone`, which we we used to
// configure `testLoader`:
// ```
    ASSERT(newYorkTimeZone == resultNewYork);
// ```

      } break;
      case 4: {
        // --------------------------------------------------------------------
        // PRINT AND OUTPUT OPERATOR
        //   Ensure that the values in the object can be formatted
        //   appropriately on an `ostream` in some standard, human-readable
        //   form.
        //
        // Concerns:
        // 1. The `print` method writes the value to the specified `ostream`.
        //
        // 2. The `print` method writes the value in the intended format.
        //
        // 3. The output using `s << obj` is the same as `obj.print(s, 0, -1)`.
        //
        // 4. The `print` method signature and return value is standard.
        //
        // 5. The output `operator<<` signature and return value is standard.
        //
        // 6. The `print` method returns the address of supplied stream.
        //
        // 7. The output `operator<<` returns the address of supplied stream.
        //
        // Plan:
        // 1. Use the addresses of the `print` method and `operator<<` defined
        //    in this component to initialize, respectively, pointers to member
        //    and free functions having the appropriate structure.  (C-4, 5)
        //
        // 2. Create several `baltzo::TestLoader` objects, each set with a
        //    different number number, [ 0 .. 3 ], of `baltzo::Zoneinfo`
        //    objects.  In turn, format each object into one of two
        //    `ostringstream` objects, using the object's `print` method (with
        //    a `level` of 0 and a `spacesPerLevel` of -1) to one
        //    `ostringstream` and the `operator<<` to the other
        //    `ostringstream`.  Compare the formatted strings from the two
        //    `ostringstream` objects.  Compare the address of the return value
        //    of the `operator<<` with the address of the given `ostringstream`
        //    object.  (C-3, 7)
        //
        // 2. Using the table-driven technique: (C-1, 2, 6)
        //   1. Prepare two `baltzo::TestLoader` objects: one empty, the other
        //      set with a `baltzo::Zoneinfo` object.
        //   2. Create a table of selected combinations of the two objects
        //      (`obj0` and `obj1`) for various values for the formatting
        //      parameters (`level` and `spacesPerLevel`), along with the
        //      expected output.  Each of the formatting parameters has three
        //      qualitatively different regions of values so there are 9
        //      combinations for each of the two objects.
        //      - The expected results are computed at run-time as a
        //        combination of the formatting done explicitly in this
        //        component and the results (subject to change) from invoking
        //        the `print` method of the `baltzo::Zoneinfo` object (with
        //        appropriate parameters).
        //      - Note that table is atypically non-`static` to allow its
        //        destruction of allocated members before the destruction of
        //        the test allocators in `main`.
        //
        // Testing:
        //   ostream& print(ostream& s, int level = 0, sPL = 4) const;
        //   operator<<(ostream& s, const baltzo::TestLoader& tl);
        // --------------------------------------------------------------------
        if (verbose) cout << endl << "PRINT AND OUTPUT OPERATOR" << endl
                                  << "=========================" << endl;
        if (verbose) cout << "\nAssign the address of print "
                             "and output operator to a variable." << endl;
        {
            using namespace baltzo;
            typedef ostream& (Obj::*funcPtr)(ostream&, int, int) const;
            typedef ostream& (*operatorPtr)(ostream&, const Obj&);

            // Verify that the signature and return type is standard.

            funcPtr     print      = &Obj::print;
            operatorPtr operatorOp = operator<<;

            (void)print;
            (void)operatorOp;
        }

        if (verbose) cout <<
                           "\nVerify `operator<<`."
                          << endl;

        {
            const char *nyId     = "America/New_York";
            const char *londonId = "Europe/London";
            const char *tokyoId  = "Asia/Tokyo";

            baltzo::Zoneinfo newYork(Z); newYork.setIdentifier(nyId);
            baltzo::Zoneinfo london(Z);   london.setIdentifier(londonId);
            baltzo::Zoneinfo tokyo(Z);     tokyo.setIdentifier(tokyoId);

            // Add some bogus data
            baltzo::LocalTimeDescriptor     nyType(-10, true, "NYTIME",     Z);
            baltzo::LocalTimeDescriptor londonType( 10, true, "LONDONTIME", Z);
            baltzo::LocalTimeDescriptor  tokyoType( 10, true, "TOKYOTIME",  Z);

           const bdlt::Datetime NY_DATETIME(2009, 2, 1, 1);
           const bdlt::Datetime LONDON_DATETIME(2009, 2, 1, 1);
           const bdlt::Datetime TOKYO_DATETIME(2009, 2, 1, 1);

            const bsls::Types::Int64 NY_INT64     =
                                bdlt::EpochUtil::convertToTimeT64(NY_DATETIME);
            const bsls::Types::Int64 LONDON_INT64 =
                            bdlt::EpochUtil::convertToTimeT64(LONDON_DATETIME);
            const bsls::Types::Int64 TOKYO_INT64  =
                             bdlt::EpochUtil::convertToTimeT64(TOKYO_DATETIME);

            newYork.addTransition(NY_INT64, nyType);
            london.addTransition(LONDON_INT64, londonType);
            tokyo.addTransition(TOKYO_INT64, tokyoType);

            Obj obj0(Z);

            Obj obj1(Z); obj1.setTimeZone(newYork);

            Obj obj2(Z); obj2.setTimeZone(newYork);
                         obj2.setTimeZone(london);

            Obj obj3(Z); obj3.setTimeZone(newYork);
                         obj3.setTimeZone(london);
                         obj3.setTimeZone(tokyo);

            ostringstream osM, osO;

            ostream& ret0 = osO << obj0; obj0.print(osM, 0, -1);
            ASSERT(osM.str() == osO.str());
            ASSERT(&osO      == &ret0);

            ostream& ret1 = osO << obj1; obj1.print(osM, 0, -1);
            ASSERT(osM.str() == osO.str());
            ASSERT(&osO      == &ret1);

            ostream& ret2 = osO << obj2; obj2.print(osM, 0, -1);
            ASSERT(osM.str() == osO.str());
            ASSERT(&osO      == &ret2);

            ostream& ret3 = osO << obj3; obj3.print(osM, 0, -1);
            ASSERT(osM.str() == osO.str());
            ASSERT(&osO      == &ret3);
        }

        if (verbose) cout << "\nVerify `print` method." <<endl;

        {
            if (verbose) cout <<
                      "\nCreate a table of distinct value/format combinations."
                              << endl;

            baltzo::LocalTimeDescriptor nyType(-10, true, "NYTIME", Z);
            const bdlt::Datetime        NY_DATETIME(2009, 12, 1, 1);
            const bsls::Types::Int64    NY_INT64 =
                                bdlt::EpochUtil::convertToTimeT64(NY_DATETIME);
            baltzo::Zoneinfo            newYork(Z);
            newYork.setIdentifier("America/New_York");
            newYork.addTransition(NY_INT64, nyType);

            Obj obj0(Z);
            Obj obj1(Z); obj1.setTimeZone(newYork);

            const struct {  // non-`static`
                int         d_line;           // source line number
                const char *d_label;
                int         d_level;
                int         d_spacesPerLevel;
                const Obj  *d_obj;
                bsl::string d_expected;
            } DATA[] = {
#define NL "\n"
#define SP " "
        //LINE LABEL   LVL SPL  OBJ    EXPECTED
        //---- ------  --- ---  ------ ---------------------------------------

        { L_,  "obj0",   0,  0, &obj0,   bsl::string("[" NL, Z)
                                       + bsl::string("]" NL, Z)
                                                                             },

        { L_,  "obj0",   0,  1, &obj0,   bsl::string("[" NL, Z)
                                       + bsl::string("]" NL, Z)
                                                                             },

        { L_,  "obj0",   0, -1, &obj0,   bsl::string("[" SP, Z)
                                       + bsl::string("]"   , Z)
                                                                             },

        { L_,  "obj0",   3,  0, &obj0,   bsl::string("[" NL, Z)
                                       + bsl::string("]" NL, Z)
                                                                             },

        { L_,  "obj0",   3,  2, &obj0,   bsl::string("      ["  NL, Z)
                                       + bsl::string("      ]"  NL, Z)
                                                                             },

        { L_,  "obj0",   3, -2, &obj0,   bsl::string("      [" SP, Z)
                                       + bsl::string("]", Z)
                                                                             },

        { L_,  "obj0",  -3,  0, &obj0,   bsl::string("[" NL, Z)
                                       + bsl::string("]" NL, Z)
                                                                             },

        { L_,  "obj0",  -3,  2, &obj0,   bsl::string("[" NL, Z)
                                       + bsl::string("      ]" NL, Z)
                                                                             },

        { L_,  "obj0",  -3, -2, &obj0,   bsl::string("[" SP, Z)
                                       + bsl::string("]", Z)
                                                                             },

        { L_,  "obj1",   0,  0, &obj1,   bsl::string("[" NL, Z)
                                       + "Zoneinfo = "
                                       + fmtZoneinfoIdent1(newYork, 0, 0, Z)
                                       + bsl::string("]" NL, Z)
                                                                             },

        { L_,  "obj1",   0,  1, &obj1,   bsl::string("[" NL, Z)
                                       + " Zoneinfo = "
                                       + fmtZoneinfoIdent1(newYork, 0, 1, Z)
                                       + bsl::string("]" NL, Z)
                                                                             },

        { L_,  "obj1",   0, -1, &obj1,   bsl::string("[" SP, Z)
                                       + "Zoneinfo = "
                                       + fmtZoneinfoIdent1(newYork, 0, -1, Z)
                                       + bsl::string(SP "]"   , Z)
                                                                             },

        { L_,  "obj1",   3,  0, &obj1,   bsl::string("[" NL, Z)
                                       + "Zoneinfo = "
                                       + fmtZoneinfoIdent1(newYork, 3, 0, Z)
                                       + bsl::string("]" NL, Z)
                                                                             },

        { L_,  "obj1",   3,  2, &obj1,   bsl::string("      ["  NL, Z)
                                       + "        Zoneinfo = "
                                       + fmtZoneinfoIdent1(newYork, 3, 2, Z)
                                       + bsl::string("      ]"  NL, Z)
                                                                             },

        { L_,  "obj1",   3, -2, &obj1,   bsl::string("      ["  SP, Z)
                                       + "Zoneinfo = "
                                       + fmtZoneinfoIdent1(newYork, 3, -2, Z)
                                       + bsl::string(SP "]", Z)
                                                                             },

        { L_,  "obj1",  -3,  0, &obj1,   bsl::string("["        NL, Z)
                                       + "Zoneinfo = "
                                       + fmtZoneinfoIdent1(newYork, -3, 0, Z)
                                       + bsl::string("]"        NL, Z)
                                                                             },

        { L_,  "obj1",  -3,  2, &obj1,   bsl::string("["         NL, Z)
                                       + "        Zoneinfo = "
                                       + fmtZoneinfoIdent1(newYork, -3, 2, Z)
                                       + bsl::string("      ]"   NL, Z)
                                                                             },

        { L_,  "obj1",  -3, -2, &obj1,   bsl::string("[" SP, Z)
                                       + "Zoneinfo = "
                                       + fmtZoneinfoIdent1(newYork, -3, -2, Z)
                                       + bsl::string(SP "]", Z)
                                                                             },
#undef NL
#undef SP
            };

            const int NUM_DATA = sizeof DATA / sizeof *DATA;

            if (verbose) cout << "\nTesting with various print specifications."
                              << endl;
            {
                for (int ti = 0; ti < NUM_DATA; ++ti) {
                    const int         LINE   = DATA[ti].d_line;
                    const char       *LABEL  = DATA[ti].d_label;
                    const int         LVL    = DATA[ti].d_level;
                    const int         SPL    = DATA[ti].d_spacesPerLevel;
                    const Obj * const OBJ    = DATA[ti].d_obj;
                    const bsl::string EXP    = DATA[ti].d_expected;

                    if (veryVerbose) { T_ P_(LVL) P_(SPL) P(LABEL) }
                    if (veryVeryVerbose) { T_ T_ Q(EXPECTED) cout << EXP; }

                    ostringstream os;
                    ostream&      ret = OBJ->print(os, LVL, SPL);

                    LOOP3_ASSERT(LINE,
                                 LVL,
                                 SPL,
                                 (&os == &ret));

                    if (veryVeryVerbose) { P(os.str()) }

                    LOOP5_ASSERT(LINE,
                                 LVL,
                                 SPL,
                                 EXP,
                                 os.str(),
                                 EXP == os.str());
                }
            }
        }

      } break;
      case 3: {
        // --------------------------------------------------------------------
        // TESTING MANIPULATORS AND ACCESSORS
        //
        // Concerns:
        // 1. Objects installed by either of the overloaded `setTimeZone`
        //    methods are treated identically.
        //
        // 2. Installing an object with a unique time-zone identifier does not
        //    affect any previously installed objects.
        //
        // 3. Installing an object with a time-zone identifier matching one
        //    previously installed changes only the previously installed
        //    object.
        //
        // 4. QoI: Asserted precondition violations are detected when enabled.
        //
        // Plan:
        // 1. For each of several time-zone identifiers create a
        //    `baltzo::Zoneinfo` object; for one time-zone identifier create no
        //    corresponding `baltzo::Zoneinfo` object.
        //   1. Create a default (empty) `baltzo::TestLoader`.
        //   2. Using the `setTimeZone` method, insert each of the
        //      `baltzo::Zoneinfo` objects into the `baltzo::TestLoader`
        //      object.
        //   3. Confirm via the `loadTimeZone` method that each insertion has
        //      made available the inserted object and that all other
        //      previously inserted objects are still accessible and unchanged.
        //      (C-2)
        //   4. Create an additional `baltzo::Zoneinfo` object with a time-zone
        //      identifier matching one of the previously inserted object but
        //      differing in other attributes.  Insert this object and confirm
        //      that the object returned for that time-zone identifier now
        //      matches the new object and that no other object in the
        //      `baltzo::Zoneinfo` object has been changed.  (C-3)
        //
        // 2. Repeat P-1 (except P-1.4) using binary data as a source for the
        //    several objects.  (C-1)
        //
        // 3. Verify that, in appropriate build modes, defensive checks are
        //    triggered for invalid attribute values, but not triggered for
        //    adjacent valid ones (using the `BSLS_ASSERTTEST_*` macros).
        //    (C-7)
        //
        // Testing:
        //   void setTimeZone(const baltzo::Zoneinfo& tz);
        //   int setTimeZone(const char *tzId, const char *data, int count);
        //   int loadTimeZone(baltzo::Zoneinfo *result, const char *tzId);
        // --------------------------------------------------------------------

        if (verbose) cout << "\nTESTING MANIPULATORS AND ACCESSOR"
                          << "\n=================================" << endl;

        if (verbose) cout << "\nWith `setTimezone` object interface" << endl;

        {
            const char *nyId     = "America/New_York";
            const char *londonId = "Europe/London";
            const char *tokyoId  = "Asia/Tokyo";
            const char *badId    = "BAD";

            baltzo::Zoneinfo newYork(Z); newYork.setIdentifier(nyId);
            baltzo::Zoneinfo london(Z);   london.setIdentifier(londonId);
            baltzo::Zoneinfo tokyo(Z);     tokyo.setIdentifier(tokyoId);

            // Add some bogus data
            baltzo::LocalTimeDescriptor     nyType(-10, true, "NYTIME",     Z);
            baltzo::LocalTimeDescriptor londonType( 10, true, "LONDONTIME", Z);
            baltzo::LocalTimeDescriptor  tokyoType( 10, true, "TOKYOTIME",  Z);

            const bdlt::Datetime NY_DATETIME(2009, 2, 1, 1);
            const bdlt::Datetime LONDON_DATETIME(2009, 2, 1, 1);
            const bdlt::Datetime TOKYO_DATETIME(2009, 2, 1, 1);

            const bsls::Types::Int64 NY_INT64     =
                                bdlt::EpochUtil::convertToTimeT64(NY_DATETIME);
            const bsls::Types::Int64 LONDON_INT64 =
                            bdlt::EpochUtil::convertToTimeT64(LONDON_DATETIME);
            const bsls::Types::Int64 TOKYO_INT64  =
                             bdlt::EpochUtil::convertToTimeT64(TOKYO_DATETIME);

            newYork.addTransition(NY_INT64,     nyType);
            london.addTransition(LONDON_INT64, londonType);
            tokyo.addTransition(TOKYO_INT64,  tokyoType);

            // ---------------------------------------------------------
            // Add a `baltzo::Zoneinfo` objects via the object interface.
            // ---------------------------------------------------------

            int             rc;
            baltzo::Zoneinfo timeZone;
            Obj             mX;

            rc = mX.loadTimeZone(&timeZone, nyId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, londonId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, tokyoId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, badId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);

            mX.setTimeZone(newYork);

            rc = mX.loadTimeZone(&timeZone, nyId);
            ASSERT(0                                       == rc);
            ASSERT(newYork                                 == timeZone);
            rc = mX.loadTimeZone(&timeZone, londonId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, tokyoId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, badId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);

            mX.setTimeZone(london);

            rc = mX.loadTimeZone(&timeZone, nyId);
            ASSERT(0                                       == rc);
            ASSERT(newYork                                 == timeZone);
            rc = mX.loadTimeZone(&timeZone, londonId);
            ASSERT(0                                       == rc);
            ASSERT(london                                  == timeZone);
            rc = mX.loadTimeZone(&timeZone, tokyoId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, badId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);

            mX.setTimeZone(tokyo);

            rc = mX.loadTimeZone(&timeZone, nyId);
            ASSERT(0                                       == rc);
            ASSERT(newYork                                 == timeZone);
            rc = mX.loadTimeZone(&timeZone, londonId);
            ASSERT(0                                       == rc);
            ASSERT(london                                  == timeZone);
            rc = mX.loadTimeZone(&timeZone, tokyoId);
            ASSERT(0                                       == rc);
            ASSERT(tokyo                                   == timeZone);
            rc = mX.loadTimeZone(&timeZone, badId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);

            // ---------------------------------------------------------------
            // Create, `newYorkPrime`, a `baltzo::Zoneinfo` object, an object
            // with the same time-zone identifier as the `newYork` object,
            // but different attributes otherwise.
            // ---------------------------------------------------------------

            baltzo::Zoneinfo newYorkPrime(Z); newYorkPrime.setIdentifier(
                                                         newYork.identifier());
            baltzo::LocalTimeDescriptor nyTypePrime(
                                                   -11, false, "NYMINUTE",  Z);

            const bdlt::Datetime     NY_DATETIME_PRIME(2001, 9, 11, 2);
            const bsls::Types::Int64 NY_INT64_PRIME =
                          bdlt::EpochUtil::convertToTimeT64(NY_DATETIME_PRIME);
            newYorkPrime.addTransition(NY_INT64_PRIME, nyTypePrime);

            ASSERT(newYork != newYorkPrime);

            mX.setTimeZone(newYorkPrime);

            rc = mX.loadTimeZone(&timeZone, nyId);
            ASSERT(0                                       == rc);
            ASSERT(newYorkPrime                            == timeZone);
            rc = mX.loadTimeZone(&timeZone, londonId);
            ASSERT(0                                       == rc);
            ASSERT(london                                  == timeZone);
            rc = mX.loadTimeZone(&timeZone, tokyoId);
            ASSERT(0                                       == rc);
            ASSERT(tokyo                                   == timeZone);
            rc = mX.loadTimeZone(&timeZone, badId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
        }

        if (verbose) cout << "\nWith `setTimezone` raw interface" << endl;

        {
            int                       rc;

            bdlsb::FixedMemInStreamBuf bufNewYork(
                    (const char*) AMERICA_NEW_YORK_DATA,
                    sizeof(AMERICA_NEW_YORK_DATA));
            bsl::istream              streamNewYork(&bufNewYork);
            baltzo::Zoneinfo           newYork;
            rc = baltzo::ZoneinfoBinaryReader::read(&newYork, streamNewYork);
            ASSERT(0 == rc);
            newYork.setIdentifier(AMERICA_NEW_YORK_ID);

            bdlsb::FixedMemInStreamBuf bufRome(
                    (const char*) EUROPE_ROME_DATA,
                    sizeof(EUROPE_ROME_DATA));
            bsl::istream              streamRome(&bufRome);
            baltzo::Zoneinfo           rome;
            rc = baltzo::ZoneinfoBinaryReader::read(&rome, streamRome);
            ASSERT(0 == rc);
            rome.setIdentifier(EUROPE_ROME_ID);

            bdlsb::FixedMemInStreamBuf bufSaigon(
                    (const char*) ASIA_SAIGON_DATA,
                    sizeof(ASIA_SAIGON_DATA));
            bsl::istream              streamSaigon(&bufSaigon);
            baltzo::Zoneinfo           saigon;
            rc = baltzo::ZoneinfoBinaryReader::read(&saigon, streamSaigon);
            ASSERT(0 == rc);
            saigon.setIdentifier(ASIA_SAIGON_ID);

            // -------------------------------------------------------
            // Add `baltzo::Zoneinfo` objects via the binary interface.
            // -------------------------------------------------------

            const char      *BAD_ID = "BAD";
            baltzo::Zoneinfo  timeZone;
            Obj              mX;

            rc = mX.loadTimeZone(&timeZone, AMERICA_NEW_YORK_ID);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, EUROPE_ROME_ID);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, ASIA_SAIGON_ID);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, BAD_ID);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);

            mX.setTimeZone(
                        AMERICA_NEW_YORK_ID,
                        reinterpret_cast<const char  *>(AMERICA_NEW_YORK_DATA),
                        sizeof(AMERICA_NEW_YORK_DATA));

            rc = mX.loadTimeZone(&timeZone, AMERICA_NEW_YORK_ID);
            ASSERT(0                                       == rc);
            ASSERT(newYork                                 == timeZone);
            rc = mX.loadTimeZone(&timeZone, EUROPE_ROME_ID);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, ASIA_SAIGON_ID);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, BAD_ID);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);

            mX.setTimeZone(EUROPE_ROME_ID,
                           reinterpret_cast<const char  *>(EUROPE_ROME_DATA),
                           sizeof(EUROPE_ROME_DATA));

            rc = mX.loadTimeZone(&timeZone, AMERICA_NEW_YORK_ID);
            ASSERT(0                                       == rc);
            ASSERT(newYork                                 == timeZone);
            rc = mX.loadTimeZone(&timeZone, EUROPE_ROME_ID);
            ASSERT(0                                       == rc);
            ASSERT(rome                                    == timeZone);
            rc = mX.loadTimeZone(&timeZone, ASIA_SAIGON_ID);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, BAD_ID);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);

            mX.setTimeZone(ASIA_SAIGON_ID,
                           reinterpret_cast<const char  *>(ASIA_SAIGON_DATA),
                           sizeof(ASIA_SAIGON_DATA));

            rc = mX.loadTimeZone(&timeZone, AMERICA_NEW_YORK_ID);
            ASSERT(0                                       == rc);
            ASSERT(newYork                                 == timeZone);
            rc = mX.loadTimeZone(&timeZone, EUROPE_ROME_ID);
            ASSERT(0                                       == rc);
            ASSERT(rome                                    == timeZone);
            rc = mX.loadTimeZone(&timeZone, ASIA_SAIGON_ID);
            ASSERT(0                                       == rc);
            ASSERT(saigon                                  == timeZone);
            rc = mX.loadTimeZone(&timeZone, BAD_ID);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
        }

        if (verbose) cout << "\nNegative Testing." << endl;

        {
            bsls::AssertTestHandlerGuard hG;

            Obj obj;

            if (veryVerbose) cout << "\t'setTimeZone'" << endl;

            {

                ASSERT_FAIL(obj.setTimeZone(
                        0,
                        reinterpret_cast<const char  *>(AMERICA_NEW_YORK_DATA),
                        sizeof(AMERICA_NEW_YORK_DATA)));
                ASSERT_FAIL(obj.setTimeZone(
                                               AMERICA_NEW_YORK_ID,
                                               0,
                                               sizeof(AMERICA_NEW_YORK_DATA)));
                ASSERT_FAIL(obj.setTimeZone(
                        AMERICA_NEW_YORK_ID,
                        reinterpret_cast<const char  *>(AMERICA_NEW_YORK_DATA),
                        -1));
                ASSERT_PASS(obj.setTimeZone(
                        AMERICA_NEW_YORK_ID,
                        reinterpret_cast<const char  *>(AMERICA_NEW_YORK_DATA),
                        sizeof(AMERICA_NEW_YORK_DATA)));
            }

            if (veryVerbose) cout << "\t'loadTimeZone'" << endl;

            {
                baltzo::Zoneinfo result;

                ASSERT_FAIL(obj.loadTimeZone(0,
                                             AMERICA_NEW_YORK_ID));
                ASSERT_FAIL(obj.loadTimeZone(&result,
                                             0));
                ASSERT_PASS(obj.loadTimeZone(&result,
                                             AMERICA_NEW_YORK_ID));
            }
        }

      } break;
      case 2: {
        // --------------------------------------------------------------------
        // CTOR AND DTOR
        //   Ensure that we can use the constructor to create an
        //   `baltzo::TestLoader` object, add `baltzo::Zoneinfo` objects,
        //   access added `baltzo::Zoneinfo` objects, and use the
        //   destructor to destroy the `baltzo::TestLoader` object safely.
        //   Although the `setTimeZone` and `loadTimeZone` methods are used
        //   here, they are not thoroughly tested until case 3.
        //
        // Concerns:
        // 1. If an allocator is *not* supplied to the default constructor, the
        //    default allocator in effect at the time of construction becomes
        //    the object allocator for the resulting object.
        //
        // 2. If an allocator is supplied to the default constructor, that
        //    allocator becomes the object allocator for the resulting object.
        //
        // 3. Supplying a default-constructed allocator has the same effect as
        //    not supplying an allocator.
        //
        // 4. Any memory allocation is from the object allocator.
        //
        // 5. Every object releases any allocated memory at destruction.
        //
        // 6. Any memory allocation is exception neutral.
        //
        // 7. Verify that no temporary memory is allocated from the object
        //    allocator.
        //
        // 8. `get_allocator` returns an allocator equal to the one used to
        //    contruct the `TestLoader`.
        //
        // Plan:
        // 1. Create a `baltzo::Zoneinfo` object.
        //
        // 2. Using a loop-based approach, default-construct three distinct
        //    objects in turn, each configured differently: (a) without passing
        //    an allocator, (b) passing a default-constructed allocator
        //    explicitly, and (c) passing in an allocator constructed from the
        //    address of a test allocator, and (d) passing in an allocator
        //    constructed from the address of a test allocator distinct from
        //    the default.  For each of these three iterations: (C-1,2,3)
        //
        //   1. Create three `bslma::TestAllocator` objects, and install one as
        //      as the current default allocator (note that a ubiquitous test
        //      allocator is already installed as the global allocator).
        //
        //   2. Use the (default) constructor to dynamically create an object,
        //      configured appropriately (see P-2) using a distinct test
        //      allocator for the object's footprint.
        //
        //   3. Use the `get_allocator` accessor of each underlying attribute
        //      capable of allocating memory to ensure that its object
        //      allocator is properly installed; also apply the (as yet
        //      unproven) `allocator` accessor of the object under test.
        //
        //   4. Verify that memory is allocated from the proper allocators.
        //      (C-4)
        //
        //   5. Use the `setTimeZone` (as yet unproven) method to install the
        //      previously created `baltzo::Zoneinfo` object.  Use the (as yet
        //      unproven) `loadTimeZone` method to confirm that the object was
        //      successfully inserted.
        //
        //   6. Verify that memory is allocated from the non-object allocator
        //      only when the object is configured to use a non-default
        //      allocator.  (C-4, 7)
        //
        //   7. Destroy the `baltzo::TestLoader` object and verify that all
        //      allocated memory is recovered.  (C-5)
        //
        //   8. In a separate block, test for exception-neutrality using the
        //      standard `BSLMA_TESTALLOCATOR_EXCEPTION*` macros.  (C-6)
        //
        // Testing:
        //   TestLoader();
        //   TestLoader(const allocator_type& allocator);
        //   ~TestLoader();
        //   void setTimeZone(const baltzo::Zoneinfo& tz);
        //   allocator_type get_allocator() const;
        // --------------------------------------------------------------------

        if (verbose) cout << "\nCTOR AND DTOR"
                          << "\n=============" << endl;

        if (verbose) cout << "\nEstablish suitable member object." << endl;

        const char *nyId  = "America/New_York";
        const char *badId = "BAD";

        baltzo::Zoneinfo newYork(Z); newYork.setIdentifier(nyId);

        // Add some bogus data
        baltzo::LocalTimeDescriptor nyType(-10, true, "NYTIME", Z);

        const bdlt::Datetime     NY_DATETIME(2009, 12, 1, 1);
        const bsls::Types::Int64 NY_INT64    =
                                bdlt::EpochUtil::convertToTimeT64(NY_DATETIME);

        newYork.addTransition(NY_INT64, nyType);

        if (verbose) cout << "\nTesting with various allocator configurations."
                          << endl;

        for (char cfg = 'a'; cfg <= 'd'; ++cfg) {

            const char CONFIG = cfg;  // how we specify the allocator

            if (verbose) P(CONFIG);

            bslma::TestAllocator fa("footprint", veryVeryVeryVerbose);
            bslma::TestAllocator da("default",   veryVeryVeryVerbose);
            bslma::TestAllocator sa("supplied",  veryVeryVeryVerbose);

            bslma::DefaultAllocatorGuard guard(&da);

            Obj                  *objPtr = 0;
            bslma::TestAllocator *objAllocatorPtr = 0;

            switch (CONFIG) {
              case 'a': {
                objAllocatorPtr = &da;
                objPtr          = new (fa) Obj();

              } break;
              case 'b': {
                objAllocatorPtr = &da;
                objPtr          = new (fa) Obj(Obj::allocator_type());
              } break;
              case 'c': {
                objAllocatorPtr = &sa;
                objPtr          = new (fa) Obj(objAllocatorPtr);
              } break;
              case 'd': {
                objAllocatorPtr = &sa;
                Obj::allocator_type alloc(objAllocatorPtr);
                objPtr = new (fa) Obj(alloc);
              } break;
              default: {
                BSLS_ASSERT_OPT(false && "Bad allocator Config.");
              } break;
            }

            if (verbose) Q("Object Constructed");

            Obj& mX = *objPtr; const Obj& X = mX;

            bslma::TestAllocator& oa  = *objAllocatorPtr;
            bslma::TestAllocator& noa = (&da == &oa) ? sa : da;

            // -----------------------------------------------------
            // QOA: Default allocated `TestLoaders` do not allocate.
            // -----------------------------------------------------

            ASSERTV(CONFIG,
                    oa.numBlocksTotal(),
                    0 == oa.numBlocksTotal());

            ASSERTV(CONFIG,
                    noa.numBlocksTotal(),
                    0 == noa.numBlocksTotal());

            // -------------------------------
            // Add a `baltzo::Zoneinfo` object.
            // -------------------------------
            mX.setTimeZone(newYork);

            baltzo::Zoneinfo timeZone(Z);
            int              rc;
            rc = mX.loadTimeZone(&timeZone, badId);
            ASSERT(baltzo::ErrorCode::k_UNSUPPORTED_ID == rc);
            rc = mX.loadTimeZone(&timeZone, nyId);
            ASSERT(0       == rc);
            ASSERT(newYork == timeZone);

            // -------------------------------------------------------
            // Verify any attribute allocators are installed properly.
            // -------------------------------------------------------

            ASSERTV(CONFIG, &oa == X.get_allocator());

            // -------------------------------------------------
            // Verify allocation only from the proper allocator.
            // -------------------------------------------------

            ASSERTV(CONFIG,
                    oa.numBlocksTotal(),
                    0 != oa.numBlocksTotal());

            ASSERTV(CONFIG,
                    noa.numBlocksTotal(),
                    0 == noa.numBlocksTotal());

            // ------------------------------------------------
            // Reclaim dynamically allocated object under test.
            // ------------------------------------------------

            fa.deleteObject(objPtr);

            // Verify all memory is released on object destruction.

            ASSERTV(CONFIG,
                    fa.numBlocksInUse(),
                    0 == fa.numBlocksInUse());
            ASSERTV(CONFIG,
                    oa.numBlocksInUse(),
                    0 == oa.numBlocksInUse());
            ASSERTV(CONFIG,
                    noa.numBlocksInUse(),
                    0 == noa.numBlocksInUse());

            // -------------------------------------------------------------
            // Double check that at least some object memory got allocated
            // (in addition to the block allocated for the map by the CTOR).
            // -------------------------------------------------------------
            ASSERTV(CONFIG, 1 <= oa.numBlocksTotal());
        }

        if (verbose) cout << "\nTesting with injected exceptions." << endl;

        {
            bslma::TestAllocator da("default",  veryVeryVeryVerbose);
            bslma::TestAllocator sa("supplied", veryVeryVeryVerbose);

            bslma::DefaultAllocatorGuard guard(&da);

            BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN(sa) {
               if (veryVeryVerbose) { T_ T_ Q(ExceptionTestBody) }
               Obj obj(&sa);
               obj.setTimeZone(newYork);
            } BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END

            LOOP_ASSERT(da.numBlocksInUse(), !da.numBlocksInUse());
            LOOP_ASSERT(sa.numBlocksInUse(), !sa.numBlocksInUse());
        }

      } break;
      case 1: {
        // --------------------------------------------------------------------
        // BREATHING TEST:
        //   Developers' Sandbox.
        //
        // Plan:
        //   Perform and ad-hoc test of the creators, modifiers, and accessors.
        //
        // Testing:
        //   This "test" *exercises* basic functionality, but (definitively)
        //   *tests* nothing.
        // --------------------------------------------------------------------

        if (verbose) cout << endl << "BREATHING TEST" << endl
                                  << "==============" << endl;

        const char *nyId     = "America/New_York";
        const char *londonId = "Europe/London";
        const char *tokyoId  = "Asia/Tokyo";
        const char *badId    = "BAD";

        baltzo::Zoneinfo newYork(Z); newYork.setIdentifier(nyId);
        baltzo::Zoneinfo london(Z);  london.setIdentifier(londonId);
        baltzo::Zoneinfo tokyo(Z);   tokyo.setIdentifier(tokyoId);

        // Add some bogus data
        baltzo::LocalTimeDescriptor     nyType(-10, true, "NYTIME",     Z);
        baltzo::LocalTimeDescriptor londonType( 10, true, "LONDONTIME", Z);
        baltzo::LocalTimeDescriptor  tokyoType( 10, true, "TOKYOTIME",  Z);

        const bdlt::Datetime NY_DATETIME(2009, 12, 1, 1);
        const bdlt::Datetime LONDON_DATETIME(2009, 12, 1, 1);
        const bdlt::Datetime TOKYO_DATETIME(2009, 12, 1, 1);

        const bsls::Types::Int64 NY_INT64     =
                                bdlt::EpochUtil::convertToTimeT64(NY_DATETIME);
        const bsls::Types::Int64 LONDON_INT64 =
                            bdlt::EpochUtil::convertToTimeT64(LONDON_DATETIME);
        const bsls::Types::Int64 TOKYO_INT64  =
                             bdlt::EpochUtil::convertToTimeT64(TOKYO_DATETIME);

        newYork.addTransition(NY_INT64, nyType);
        london.addTransition(LONDON_INT64, londonType);
        tokyo.addTransition (TOKYO_INT64, tokyoType);

        Obj x(Z);

        baltzo::Zoneinfo value(Z);
        ASSERT(Err::k_UNSUPPORTED_ID == x.loadTimeZone(&value, badId));
        ASSERT(Err::k_UNSUPPORTED_ID == x.loadTimeZone(&value, nyId));
        ASSERT(Err::k_UNSUPPORTED_ID == x.loadTimeZone(&value, londonId));
        ASSERT(Err::k_UNSUPPORTED_ID == x.loadTimeZone(&value, tokyoId));

        x.setTimeZone(newYork);
        x.setTimeZone(london);
        x.setTimeZone(tokyo);

        ASSERT(Err::k_UNSUPPORTED_ID == x.loadTimeZone(&value, badId));
        ASSERT(0     == x.loadTimeZone(&value, nyId));
        ASSERT(value == newYork);
        ASSERT(0     == x.loadTimeZone(&value, londonId));
        ASSERT(value == london);
        ASSERT(0     == x.loadTimeZone(&value, tokyoId));
        ASSERT(value == tokyo);

        if (veryVerbose) {
            cout << "\tTest loading binary data." << endl;
        }
        ASSERT(0 == x.setTimeZone(ASIA_BANGKOK_ID,
                            reinterpret_cast<const char  *>(ASIA_BANGKOK_DATA),
                            sizeof(ASIA_BANGKOK_DATA)));
        ASSERT(0 == x.loadTimeZone(&value, ASIA_BANGKOK_ID));

        // Bangkok data file has 1 transition, +1 for the first
        // `bdlt::Datetime`

        LOOP_ASSERT(value.numTransitions(), 3 == value.numTransitions());

        {
            LogVerbosityGuard guard;
            ASSERT(0 != x.setTimeZone(ASIA_BANGKOK_ID,
                            reinterpret_cast<const char  *>(ASIA_BANGKOK_DATA),
                            15));
        }
      } break;
      default: {
        cerr << "WARNING: CASE `" << test << "' NOT FOUND." << endl;
        testStatus = -1;
      }
    }

    if (testStatus > 0) {
        cerr << "Error, non-zero test status = " << testStatus << "." << endl;
    }
    return testStatus;
}

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
